package com.ruoyi.rabbitmq.service;

import com.ruoyi.rabbitmq.config.RabbitMQConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * RabbitMQ管理服务
 * 
 * @author ruoyi
 */
@Service
@ConditionalOnProperty(name = "spring.rabbitmq.enabled", havingValue = "true", matchIfMissing = true)
public class RabbitMQManager
{
    private static final Logger log = LoggerFactory.getLogger(RabbitMQManager.class);

    @Autowired
    private RabbitAdmin rabbitAdmin;

    @Autowired
    private ConnectionFactory connectionFactory;

    /**
     * 创建队列
     * 
     * @param queueName 队列名称
     * @param durable 是否持久化
     * @param exclusive 是否排他
     * @param autoDelete 是否自动删除
     * @param arguments 队列参数
     * @return 是否创建成功
     */
    public boolean createQueue(String queueName, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
    {
        try
        {
            Queue queue = new Queue(queueName, durable, exclusive, autoDelete, arguments);
            rabbitAdmin.declareQueue(queue);
            log.info("队列创建成功: {}", queueName);
            return true;
        }
        catch (Exception e)
        {
            log.error("队列创建失败: {}", queueName, e);
            return false;
        }
    }

    /**
     * 创建直连交换机
     * 
     * @param exchangeName 交换机名称
     * @param durable 是否持久化
     * @param autoDelete 是否自动删除
     * @return 是否创建成功
     */
    public boolean createDirectExchange(String exchangeName, boolean durable, boolean autoDelete)
    {
        try
        {
            DirectExchange exchange = new DirectExchange(exchangeName, durable, autoDelete);
            rabbitAdmin.declareExchange(exchange);
            log.info("直连交换机创建成功: {}", exchangeName);
            return true;
        }
        catch (Exception e)
        {
            log.error("直连交换机创建失败: {}", exchangeName, e);
            return false;
        }
    }

    /**
     * 创建主题交换机
     * 
     * @param exchangeName 交换机名称
     * @param durable 是否持久化
     * @param autoDelete 是否自动删除
     * @return 是否创建成功
     */
    public boolean createTopicExchange(String exchangeName, boolean durable, boolean autoDelete)
    {
        try
        {
            TopicExchange exchange = new TopicExchange(exchangeName, durable, autoDelete);
            rabbitAdmin.declareExchange(exchange);
            log.info("主题交换机创建成功: {}", exchangeName);
            return true;
        }
        catch (Exception e)
        {
            log.error("主题交换机创建失败: {}", exchangeName, e);
            return false;
        }
    }

    /**
     * 创建扇形交换机
     * 
     * @param exchangeName 交换机名称
     * @param durable 是否持久化
     * @param autoDelete 是否自动删除
     * @return 是否创建成功
     */
    public boolean createFanoutExchange(String exchangeName, boolean durable, boolean autoDelete)
    {
        try
        {
            FanoutExchange exchange = new FanoutExchange(exchangeName, durable, autoDelete);
            rabbitAdmin.declareExchange(exchange);
            log.info("扇形交换机创建成功: {}", exchangeName);
            return true;
        }
        catch (Exception e)
        {
            log.error("扇形交换机创建失败: {}", exchangeName, e);
            return false;
        }
    }

    /**
     * 绑定队列到交换机
     * 
     * @param queueName 队列名称
     * @param exchangeName 交换机名称
     * @param routingKey 路由键
     * @return 是否绑定成功
     */
    public boolean bindQueueToExchange(String queueName, String exchangeName, String routingKey)
    {
        try
        {
            Binding binding = BindingBuilder.bind(new Queue(queueName))
                    .to(new DirectExchange(exchangeName))
                    .with(routingKey);
            rabbitAdmin.declareBinding(binding);
            log.info("队列绑定成功: {} -> {} (routingKey: {})", queueName, exchangeName, routingKey);
            return true;
        }
        catch (Exception e)
        {
            log.error("队列绑定失败: {} -> {}", queueName, exchangeName, e);
            return false;
        }
    }

    /**
     * 绑定队列到主题交换机
     * 
     * @param queueName 队列名称
     * @param exchangeName 交换机名称
     * @param routingKey 路由键
     * @return 是否绑定成功
     */
    public boolean bindQueueToTopicExchange(String queueName, String exchangeName, String routingKey)
    {
        try
        {
            Binding binding = BindingBuilder.bind(new Queue(queueName))
                    .to(new TopicExchange(exchangeName))
                    .with(routingKey);
            rabbitAdmin.declareBinding(binding);
            log.info("队列绑定到主题交换机成功: {} -> {} (routingKey: {})", queueName, exchangeName, routingKey);
            return true;
        }
        catch (Exception e)
        {
            log.error("队列绑定到主题交换机失败: {} -> {}", queueName, exchangeName, e);
            return false;
        }
    }

    /**
     * 绑定队列到扇形交换机
     * 
     * @param queueName 队列名称
     * @param exchangeName 交换机名称
     * @return 是否绑定成功
     */
    public boolean bindQueueToFanoutExchange(String queueName, String exchangeName)
    {
        try
        {
            Binding binding = BindingBuilder.bind(new Queue(queueName))
                    .to(new FanoutExchange(exchangeName));
            rabbitAdmin.declareBinding(binding);
            log.info("队列绑定到扇形交换机成功: {} -> {}", queueName, exchangeName);
            return true;
        }
        catch (Exception e)
        {
            log.error("队列绑定到扇形交换机失败: {} -> {}", queueName, exchangeName, e);
            return false;
        }
    }

    /**
     * 删除队列
     * 
     * @param queueName 队列名称
     * @return 是否删除成功
     */
    public boolean deleteQueue(String queueName)
    {
        try
        {
            boolean result = rabbitAdmin.deleteQueue(queueName);
            if (result)
            {
                log.info("队列删除成功: {}", queueName);
            }
            else
            {
                log.warn("队列删除失败: {}", queueName);
            }
            return result;
        }
        catch (Exception e)
        {
            log.error("队列删除异常: {}", queueName, e);
            return false;
        }
    }

    /**
     * 删除交换机
     * 
     * @param exchangeName 交换机名称
     * @return 是否删除成功
     */
    public boolean deleteExchange(String exchangeName)
    {
        try
        {
            boolean result = rabbitAdmin.deleteExchange(exchangeName);
            if (result)
            {
                log.info("交换机删除成功: {}", exchangeName);
            }
            else
            {
                log.warn("交换机删除失败: {}", exchangeName);
            }
            return result;
        }
        catch (Exception e)
        {
            log.error("交换机删除异常: {}", exchangeName, e);
            return false;
        }
    }

    /**
     * 解绑队列和交换机
     * 
     * @param queueName 队列名称
     * @param exchangeName 交换机名称
     * @param routingKey 路由键
     * @return 是否解绑成功
     */
    public boolean unbindQueueFromExchange(String queueName, String exchangeName, String routingKey)
    {
        try
        {
            rabbitAdmin.removeBinding(BindingBuilder.bind(new Queue(queueName))
                    .to(new DirectExchange(exchangeName))
                    .with(routingKey));
            log.info("队列解绑成功: {} -> {} (routingKey: {})", queueName, exchangeName, routingKey);
            return true;
        }
        catch (Exception e)
        {
            log.error("队列解绑失败: {} -> {}", queueName, exchangeName, e);
            return false;
        }
    }

    /**
     * 创建带死信队列的队列
     * 
     * @param queueName 队列名称
     * @param deadLetterExchange 死信交换机
     * @param deadLetterRoutingKey 死信路由键
     * @return 是否创建成功
     */
    public boolean createQueueWithDeadLetter(String queueName, String deadLetterExchange, String deadLetterRoutingKey)
    {
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange", deadLetterExchange);
        arguments.put("x-dead-letter-routing-key", deadLetterRoutingKey);
        
        return createQueue(queueName, true, false, false, arguments);
    }

    /**
     * 创建延迟队列
     * 
     * @param queueName 队列名称
     * @param delayMillis 延迟时间（毫秒）
     * @param targetExchange 目标交换机
     * @param targetRoutingKey 目标路由键
     * @return 是否创建成功
     */
    public boolean createDelayQueue(String queueName, long delayMillis, String targetExchange, String targetRoutingKey)
    {
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange", targetExchange);
        arguments.put("x-dead-letter-routing-key", targetRoutingKey);
        arguments.put("x-message-ttl", delayMillis);
        
        return createQueue(queueName, true, false, false, arguments);
    }

    /**
     * 获取连接信息
     * 
     * @return 连接信息
     */
    public Map<String, Object> getConnectionInfo()
    {
        Map<String, Object> info = new HashMap<>();
        try
        {
            if (connectionFactory instanceof CachingConnectionFactory)
            {
                CachingConnectionFactory cachingConnectionFactory = (CachingConnectionFactory) connectionFactory;
                info.put("host", cachingConnectionFactory.getHost());
                info.put("port", cachingConnectionFactory.getPort());
                info.put("virtualHost", cachingConnectionFactory.getVirtualHost());
                info.put("username", cachingConnectionFactory.getUsername());
                info.put("connected", cachingConnectionFactory.createConnection() != null);
            }
            else
            {
                info.put("host", "unknown");
                info.put("port", 5672);
                info.put("virtualHost", "/");
                info.put("username", "unknown");
                info.put("connected", connectionFactory.createConnection() != null);
            }
        }
        catch (Exception e)
        {
            log.error("获取连接信息失败", e);
            info.put("connected", false);
            info.put("error", e.getMessage());
        }
        return info;
    }

    /**
     * 初始化默认配置
     */
    public void initializeDefaultConfig()
    {
        log.info("开始初始化RabbitMQ默认配置...");
        
        // 创建死信交换机
        createDirectExchange(RabbitMQConfig.DEAD_LETTER_EXCHANGE, true, false);
        
        // 创建死信队列
        createQueue(RabbitMQConfig.DEAD_LETTER_QUEUE, true, false, false, null);
        
        // 绑定死信队列到死信交换机
        bindQueueToExchange(RabbitMQConfig.DEAD_LETTER_QUEUE, 
                           RabbitMQConfig.DEAD_LETTER_EXCHANGE, 
                           RabbitMQConfig.DEAD_LETTER_ROUTING_KEY);
        
        // 创建重试队列
        Map<String, Object> retryArguments = new HashMap<>();
        retryArguments.put("x-dead-letter-exchange", RabbitMQConfig.DIRECT_EXCHANGE);
        retryArguments.put("x-dead-letter-routing-key", RabbitMQConfig.DIRECT_ROUTING_KEY);
        retryArguments.put("x-message-ttl", 10000); // 10秒后重试
        createQueue(RabbitMQConfig.RETRY_QUEUE, true, false, false, retryArguments);
        
        log.info("RabbitMQ默认配置初始化完成");
    }
} 